#include <ESP8266WiFi.h>

// Wi-Fi配置
const char* ssid = "你的WIFI名称";
const char* password = "你的WIFI密码";

// APRS服务器配置
const char* host = "china.aprs2.net";
const uint16_t port = 14580;

// APRS身份信息 请遵守法律法规
//呼号计算  http://www.hocool.com/radio/aprspassword/
const char* aprsCallSign = "您的呼号";
const char* aprsPasscode = "登录码Password";

// APRS信标信息（可根据需要修改） https://aprs.tv/ 位置信息 自己获取 信息 可以修改 
const char* aprsBeaconInfo = "!3351.39N/11544.37E>ESP8266 APRS信标";

WiFiClient client;
unsigned long previousMillis = 0;           // 信标发送计时器
const long beaconInterval = 30000;          // 信标发送间隔（30秒）
unsigned long lastLoginAttemptTime = 0;     // 上次发送注册信息的时间
const long loginRetryInterval = 10000;      // 注册重试间隔（10秒，避免频繁发送）
bool isConnected = false;                   // 服务器连接状态
bool isLoggedIn = false;                    // 注册成功标志

void setup() {
  Serial.begin(115200);
  delay(10);

  // 连接Wi-Fi
  Serial.print("连接到 ");
  Serial.println(ssid);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("\nWi-Fi连接成功，IP: " + WiFi.localIP().toString());

  // 初始连接APRS服务器
  connectToAprsServer();
}

void loop() {
  // 检查服务器连接状态，断开则重连
  if (!client.connected()) {
    if (isConnected) {
      Serial.println("与APRS服务器断开连接，重置状态");
      isConnected = false;
      isLoggedIn = false;  // 断开连接后需重新注册
    }
    Serial.println("尝试重连到APRS服务器...");
    if (connectToAprsServer()) {
      Serial.println("重连服务器成功");
    } else {
      Serial.println("重连服务器失败，10秒后重试");
      delay(10000);
      return;
    }
  }

  // 处理服务器返回数据（识别注册成功响应）
  while (client.available()) {
    String line = client.readStringUntil('\n');
    Serial.print("APRS服务器: ");
    Serial.println(line);
    
    // 识别注册成功（匹配服务器验证响应）
    if (line.indexOf("verified") != -1 || 
        line.indexOf("logresp " + String(aprsCallSign) + " verified") != -1) {
      isLoggedIn = true;
      Serial.println("注册成功！后续仅发送信标");
      previousMillis = millis();  // 重置信标计时器，确保近期发送一次信标
    }
  }

  // 若已注册成功，仅定时发送信标
  if (isLoggedIn) {
    unsigned long currentMillis = millis();
    if (currentMillis - previousMillis >= beaconInterval) {
      previousMillis = currentMillis;
      sendAprsBeacon();
      Serial.print("下次信标将在 ");
      Serial.print(beaconInterval / 1000);
      Serial.println(" 秒后发送");
    }
  } 
  // 若未注册成功，定期重试发送注册信息
  else {
    unsigned long currentMillis = millis();
    // 每隔loginRetryInterval（10秒）尝试一次注册
    if (currentMillis - lastLoginAttemptTime >= loginRetryInterval) {
      lastLoginAttemptTime = currentMillis;
      sendLogin();  // 发送注册信息
      Serial.println("注册未成功，发送注册信息重试");
    }
  }
}

// 连接到APRS服务器，返回连接结果
bool connectToAprsServer() {
  if (client.connect(host, port)) {
    isConnected = true;
    Serial.println("TCP连接到APRS服务器成功");
    return true;
  } else {
    isConnected = false;
    Serial.println("TCP连接服务器失败");
    return false;
  }
}

// 发送注册信息（仅在未注册成功时调用）
void sendLogin() {
  String login = "user " + String(aprsCallSign) + " pass " + String(aprsPasscode) + 
                 " vers ESP8266_APRS 1.0 filter b/" + String(aprsCallSign);
  client.println(login);
  Serial.println("发送注册信息: " + login);
}

// 发送APRS信标（仅在注册成功后调用）
void sendAprsBeacon() {
  String beacon = String(aprsCallSign) + "-6>APRS,TCPIP*:" + String(aprsBeaconInfo);
  client.println(beacon);
  Serial.println("发送信标: " + beacon);
}